#!/usr/bin/evn python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   文件名称 :     parse_error_helper
   文件功能描述 :   功能描述
   创建人 :       小钟同学
   创建时间 :          2021/12/23
-------------------------------------------------
   修改描述-2021/12/23:         
-------------------------------------------------
"""
from typing import Any, List, Optional
from pydantic.errors import *


def parse_error(err: Any, field_names: List, raw: bool = True) -> Optional[dict]:
    """
    Parse single error object (such as pydantic-based or fastapi-based) to dict
    :param err: Error object
    :param field_names: List of names of the field that are already processed
    :param raw: Whether this is a raw error or wrapped pydantic error
    :return: dict with name of the field (or "__all__") and actual message
    """
    if isinstance(err.exc, EnumError):
        permitted_values = ", ".join([f"'{val}'" for val in err.exc.enum_values])
        message = f"Value is not a valid enumeration member; "f"permitted: {permitted_values}."
    elif isinstance(err.exc, StrRegexError):
        message = "Provided value doesn't match valid format."
    else:
        message = str(err.exc) or ""

    if not raw:
        if len(err.loc_tuple()) == 2:
            if str(err.loc_tuple()[0]) in ["body", "query"]:
                name = err.loc_tuple()[1]
            else:
                name = err.loc_tuple()[0]
        elif len(err.loc_tuple()) == 1:
            if str(err.loc_tuple()[0]) == "body":
                name = "__all__"
            else:
                name = str(err.loc_tuple()[0])
        else:
            name = "__all__"
    else:
        if len(err.loc_tuple()) == 2:
            name = str(err.loc_tuple()[0])
        elif len(err.loc_tuple()) == 1:
            name = str(err.loc_tuple()[0])
        else:
            name = "__all__"

    if name in field_names:
        return None

    if message and not any(
            [message.endswith("."), message.endswith("?"), message.endswith("!")]
    ):
        message = message + "."
    message = message.capitalize()

    print("啥都会撒的好", err.exc.code)
    print("啥都会撒的好", err.exc.limit_value)
    print("啥都会撒的好", err.exc.msg_template)
    return {"name": name,
            "code": err.exc.code,
            "limit_value": err.exc.limit_value,
            "msg_template": err.exc.msg_template,
            "message": message}


def raw_errors_to_fields(raw_errors: List) -> List[dict]:
    """
    Translates list of raw infirmary_errors (instances) into list of dicts with name/msg
    :param raw_errors: List with instances of raw error
    :return: List of dicts (1 dict for every raw error)
    """
    fields = []
    for top_err in raw_errors:
        if hasattr(top_err.exc, "raw_errors"):
            for err in top_err.exc.raw_errors:
                # This is a special case when infirmary_errors happen both in gziprequest
                # handling & internal validation
                if isinstance(err, list):
                    err = err[0]
                field_err = parse_error(
                    err,
                    field_names=list(map(lambda x: x["name"], fields)),
                    raw=True,
                )
                if field_err is not None:
                    fields.append(field_err)
        else:
            field_err = parse_error(
                top_err,
                field_names=list(map(lambda x: x["name"], fields)),
                raw=False,
            )
            if field_err is not None:
                fields.append(field_err)
    return fields
